import re
from datetime import datetime

from django.db.transaction import atomic
from organization.models import (BusinessDept, BusinessLine, Company, Employee)
from record.models import (BusinessCostRecord, IncomeRecord, Salary)
import xlrd
from xlrd.sheet import Sheet, Cell
from xlrd.book import Book
from xlrd.biffh import XL_CELL_DATE, XL_CELL_NUMBER, XL_CELL_TEXT

from utils.timezone import tzinfo


def date_convert(cell:Cell, workbook:Book):
    date_ = None
    if cell.ctype == XL_CELL_DATE:
        date_value = xlrd.xldate_as_tuple(cell.value, workbook.datemode)
        date_ = datetime(*date_value[:3])
    elif cell.ctype == XL_CELL_NUMBER:
        date_ = datetime.strptime(str(int(cell.value)), '%Y%m%d')
    elif cell.ctype == XL_CELL_TEXT:
        date_ = datetime.strptime(cell.value, '%Y%m%d')

    date_ = date_.replace(tzinfo=tzinfo)
    return date_


def retrive_company(cell:Cell, workbook:Book):
    company = Company.objects.get(name=cell.value)
    return company


def retrive_businessdept(cell:Cell, workbook:Book):
    busdept = BusinessDept.objects.get(name=cell.value)
    return busdept


def retrive_businessline(cell:Cell, workbook:Book):
    busline = BusinessLine.objects.get(name=cell.value)
    return busline


def retrive_employee(cell:Cell, workbook:Book):
    employee = Employee.objects.get(name=cell.value)
    return employee


def get_businessline(context, obj:Salary):
    # 暂时一个员工只属于一条业务线
    return obj.employee.businessline.first()


def get_month_from_file_name(context, obj:Salary):
    date_ = datetime.strptime(context.match.groups()[0], '%y%m')
    date_ = date_.replace(tzinfo=tzinfo)
    return date_


MAPPER = {
            re.compile(r'业务成本数据_.+事业部\.'): (
                BusinessCostRecord,
                (
                    ('date', 0, date_convert),
                    ('company', 1, retrive_company),
                    ('businessdept', 2, retrive_businessdept),
                    ('businessline', 3, retrive_businessline),
                    ('desc', 4, None),
                    ('cost', 5, None)
                ),
            ),
            re.compile(r'收入数据_.+事业部\.'): (
                IncomeRecord,
                (
                    ('date', 0, date_convert),
                    ('company', 1, retrive_company),
                    ('businessdept', 2, retrive_businessdept),
                    ('businessline', 3, retrive_businessline),
                    ('desc', 4, None),
                    ('income', 5, None)
                ),
            ),
            re.compile(r'人力成本数据_.+事业部_(\d{4})\.'): (
                Salary,
                (
                    ('serial_number', 0, None),
                    ('employee', 1, retrive_employee),
                    ('company', 2, retrive_company),
                    ('businessdept', 3, retrive_businessdept),
                    ('payable_salary', 4, None),
                    ('endowment_insurance_p', 5, None),
                    ('unemployment_insurance_p', 6, None),
                    ('hospitalization_insurance_p', 7, None),
                    ('reserve_fund_p', 8, None),
                    ('individual_income_tax', 9, None),
                    ('actual_salary', 10, None),
                    ('other_pay', 11, None),
                    ('fiveone_total', 12, None),
                    ('company_pay_total', 13, None),
                    ('pay_date', None, get_month_from_file_name),
                    ('businessline', None, get_businessline)
                ),
            )
        }


class SaveSheet():
    def __init__(self, sheet:Sheet,
                 match_and_key, workbook:Book):
        self.match, self.key = match_and_key
        self.sheet = sheet
        self.model, self.fields = MAPPER[self.key]
        self.workbook = workbook

    @atomic()
    def save(self):
        sheet = self.sheet
        model = self.model
        fields = self.fields
        workbook = self.workbook

        for row in range(1, sheet.nrows):
            # 创建 Model 对象
            obj = model()

            for col_tuple in fields:
                # 遍历该对象所有的 `fields`， 取出每个 `field` 的配置项
                field_name, col, fun = col_tuple
                if col is None:
                    # 不是从 excel 中取的值
                    value = fun(self, obj)
                else:
                    cell = sheet.cell(row, col)
                    if fun:
                        value = fun(cell, workbook)
                    else:
                        value = cell.value

                # 将值赋给新对象
                setattr(obj, field_name, value)

            obj.save()
